package top.anydata.lifeofcode.lifesystem.service.sys.user.impl;

import org.modelmapper.ModelMapper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import top.anydata.lifeofcode.lifesystem.dao.sys.user.*;
import top.anydata.lifeofcode.lifesystem.dto.sys.user.SysAuthPermissionDto;
import top.anydata.lifeofcode.lifesystem.dto.sys.user.SysAuthRoleDto;
import top.anydata.lifeofcode.lifesystem.entity.sys.user.SysAuthPermissionEntity;
import top.anydata.lifeofcode.lifesystem.entity.sys.user.SysAuthRoleEntity;
import top.anydata.lifeofcode.lifesystem.entity.sys.user.SysAuthRolePermissionEntity;
import top.anydata.lifeofcode.lifesystem.entity.sys.user.SysAuthUserRoleEntity;
import top.anydata.lifeofcode.lifesystem.service.sys.user.IAuthRoleService;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 功能描述:
 *
 * @author <a href="mailto:caingao@anydata.top">CainGao</a>
 * @version V_1.0
 * @date 2024/1/30 5:41 PM
 */
@Service
public class AuthRoleServiceImpl implements IAuthRoleService {

    private final ISysAuthPermissionRepository sysAuthPermissionRepository;

    private final ISysAuthRolePermissionRepository sysAuthRolePermissionRepository;

    private final ISysAuthUserRoleRepository sysAuthUserRoleRepository;

    private final ISysAuthUserRepository sysAuthUserRepository;

    private final ISysAuthRoleRepository sysAuthRoleRepository;


    private ModelMapper modelMapper = new ModelMapper();

    public AuthRoleServiceImpl(ISysAuthPermissionRepository sysAuthPermissionRepository,
                               ISysAuthRolePermissionRepository sysAuthRolePermissionRepository,
                               ISysAuthUserRoleRepository sysAuthUserRoleRepository,
                               ISysAuthUserRepository sysAuthUserRepository,
                               ISysAuthRoleRepository sysAuthRoleRepository
    ) {
        this.sysAuthPermissionRepository = sysAuthPermissionRepository;
        this.sysAuthRolePermissionRepository = sysAuthRolePermissionRepository;
        this.sysAuthUserRoleRepository = sysAuthUserRoleRepository;
        this.sysAuthUserRepository = sysAuthUserRepository;
        this.sysAuthRoleRepository = sysAuthRoleRepository;
    }

    @Override
    @Cacheable(value = "sys::common::permissions", key = "#permission.id",sync = true)
    public void createPermission(SysAuthPermissionDto permission) {
        SysAuthPermissionEntity sysAuthPermissionEntity =
                modelMapper.map(permission, SysAuthPermissionEntity.class);
        sysAuthPermissionRepository.save(sysAuthPermissionEntity);
    }

    @Override
    @CacheEvict(value = "sys::common::permissions", key = "#permission.id")
    public void updatePermission(SysAuthPermissionDto permission) {
        SysAuthPermissionEntity sysAuthPermissionEntity =
                modelMapper.map(permission, SysAuthPermissionEntity.class);
        sysAuthPermissionRepository.save(sysAuthPermissionEntity);
    }

    @Override
    public void deletePermission(int id) {
        sysAuthPermissionRepository.deleteById(id);
    }

    @Override
    @Cacheable(value = "sys::common::permissions", key = "#id")
    public SysAuthPermissionDto getPermission(int id) {
        SysAuthPermissionEntity sysAuthPermissionEntity =
                sysAuthPermissionRepository.findById(id).get();
        return modelMapper.map(sysAuthPermissionEntity, SysAuthPermissionDto.class);
    }

    @Override
    public List<SysAuthPermissionDto> getPermissionByUserId(int userId) {


        return null;
    }

    @Override
    public Page<SysAuthPermissionDto> getPermissionList(int page,int pagesize) {
        Page<SysAuthPermissionEntity> sysAuthPermissionEntities =
                sysAuthPermissionRepository.findAll(PageRequest.of(page,pagesize));
        return sysAuthPermissionEntities.map(
                sysAuthPermissionEntity ->
                        modelMapper.map(sysAuthPermissionEntity, SysAuthPermissionDto.class)
        );
    }

    @Override
    @Cacheable(value = "sys::common::roles", key = "#role.id")
    public void createRole(SysAuthRoleDto role) {
        SysAuthRoleEntity
                sysAuthRoleEntity = modelMapper.map(role, SysAuthRoleEntity.class);
        sysAuthRoleRepository.save(sysAuthRoleEntity);
    }

    @Override
    @CacheEvict(value = "sys::common::roles", key = "#role.id")
    public void updateRole(SysAuthRoleDto role) {
        SysAuthRoleEntity
                sysAuthRoleEntity = modelMapper.map(role, SysAuthRoleEntity.class);
        sysAuthRoleRepository.save(sysAuthRoleEntity);
    }

    @Override
    @CacheEvict(value = "sys::common::roles", key = "#id")
    public void deleteRole(int id) {
        sysAuthRoleRepository.deleteById(id);
    }

    @Override
    @Cacheable(value = "sys::common::roles", key = "#id")
    public SysAuthRoleDto getRole(int id) {
        SysAuthRoleEntity sysAuthRoleEntity = sysAuthRoleRepository.findById(id).get();
        return modelMapper.map(sysAuthRoleEntity, SysAuthRoleDto.class);
    }

    @Override
    public Page<SysAuthRoleDto> getRoleList(Integer pageNum, Integer pageSize) {
        Page<SysAuthRoleEntity> sysAuthRoleEntities = sysAuthRoleRepository.findAll(PageRequest.of(pageNum, pageSize));
        return sysAuthRoleEntities.map(sysAuthRoleEntity -> modelMapper.map(sysAuthRoleEntity, SysAuthRoleDto.class));
    }

    @Override
    @CacheEvict(value = "sys::common::user_roles", key = "#userId")
    public void assignRoleToUser(int userId, int roleId) {
        SysAuthUserRoleEntity sysAuthUserRoleEntity = SysAuthUserRoleEntity.builder()
                .userId(userId)
                .roleId(roleId)
                .build();
        sysAuthUserRoleRepository.save(sysAuthUserRoleEntity);
    }

    @Override
    @CacheEvict(value = "sys::common::user_roles", key = "#userId")
    public void removeRoleFromUser(int userId, int roleId) {
        sysAuthUserRoleRepository.deleteByUserIdAndRoleId(userId, roleId);
    }

    @Override
    @Cacheable(value = "sys::common::user_roles", key = "#userId",sync = true)
    public List<SysAuthRoleDto> getRolesForUser(int userId) {
        List<SysAuthRoleDto> roles = new ArrayList<>();
        List<SysAuthUserRoleEntity> entities = sysAuthUserRoleRepository.findRolesByUserId(userId);
        entities.forEach(entity -> {
            Optional<SysAuthRoleEntity> optionalEntity = sysAuthRoleRepository.findById(entity.getRoleId());
            if (optionalEntity.isPresent()) {
                SysAuthRoleDto dto = modelMapper.map(optionalEntity.get(), SysAuthRoleDto.class);
                roles.add(dto);
            }
        });
        return roles;
    }

    @Override
    @CacheEvict(value = "sys::common::role_permissions", key = "#roleId")
    public void assignPermissionToRole(int roleId, int permissionId) {
        SysAuthRolePermissionEntity rolePermission = new SysAuthRolePermissionEntity();
        rolePermission.setRoleId(roleId);
        rolePermission.setPermissionId(permissionId);
        sysAuthRolePermissionRepository.save(rolePermission);
    }

    @Override
    @CacheEvict(value = "sys::common::role_permissions", key = "#roleId")
    public void removePermissionFromRole(int roleId, int permissionId) {
        sysAuthRolePermissionRepository.deleteByRoleIdAndPermissionId(roleId, permissionId);
    }

    @Override
    @Cacheable(value = "sys::common::role_permissions", key = "#roleId",sync = true)
    public List<SysAuthPermissionDto> getPermissionsForRole(int roleId) {
        List<SysAuthPermissionDto> permissions = new ArrayList<>();
        List<SysAuthRolePermissionEntity> entities = sysAuthRolePermissionRepository.findPermissionsByRoleId(roleId);
        entities.forEach(entity -> {
            Optional<SysAuthPermissionEntity> optionalEntity = sysAuthPermissionRepository.findById(entity.getPermissionId());
            if (optionalEntity.isPresent()) {
                SysAuthPermissionDto dto = modelMapper.map(optionalEntity.get(), SysAuthPermissionDto.class);
                permissions.add(dto);
            }
        });
        return permissions;
    }
}
